#!groovy
@Library("jenkinslib") _

//func from sharelibrary调用共享库
def build=new org.devops.build()
def tools=new org.devops.tools()
def toemailF=new org.devops.toemailF()

String Tenv="${env.Tenv}"
String buildType="${env.buildType}"
String buildshell="${env.buildshell}"
String srcURL="${env.SrcURL}"
String branch="${env.branchName}"
String buildPath="${env.buildPath}"//抽包路径
String destPath="${env.destPath}"
String destIp="${env.destIp}"
Boolean rollback = (env.rollback == 'true')
Boolean isPublish = (env.isPublish == 'true')
Boolean isApollo = (env.isApollo == 'true')//是否启用了Apollo
String projectName = "${env.projectName}"
String JVM_OPTS="${env.JVM_OPTS}"?:"-server -Xss256K -Xmx512m -Xms512m -Xmn256m -XX:MetaspaceSize=256m -XX:MaxMetaspaceSize=256m"
String APOLLO_ENV="${env.APOLLO_ENV}"?:"PRO"
String PROFILE="${env.PROFILE}"?:"prod"
String APOLLO_META="${env.APOLLO_META}"?:"http://apollo-eurka-service/"
String APOLLO_NAMESPACES="${env.APOLLO_NAMESPACES}"?:"application.properties,lunling-common.properties,lunling-linkage-common.properties"
pipeline{
    agent {
        label 'master'
    }
    options {
        timestamps()
        skipDefaultCheckout()  // 禁用隐式 Checkout
        timeout(time: 1, unit: 'HOURS') //设置流水线超时
    }
    environment {
        BUILD_TIME = sh(script: "date '+%Y%m%d_%H%M%S'", returnStdout: true).trim()
        MINIO_BUCKET = 'backend-artifacts'
    }
    stages{
        stage("CheckOut"){
            when { expression { !rollback } }  // 非回滚时执行
            steps{
                script{
                    tools.PrintMsg("获取分支: ${branch}","checkout")
                    tools.PrintMsg("获取代码","checkout")
                    checkout([$class: 'GitSCM', branches: [[name: "${branch}"]], 
                        extensions: [], 
                        userRemoteConfigs: [[credentialsId: 'gitee_registry_ssh', url: "${srcURL}"]]])
                    // 记录当前commit信息用于追踪
                    env.GIT_COMMIT = sh(script: 'git rev-parse --short HEAD', returnStdout: true).trim()
                }
            }
        }
        stage("代码编译"){
            when { expression { !rollback } }  // 非回滚时执行
            steps{
                script{
                    tools.PrintMsg("代码编译","build")
                    // 使用共享库中的构建方法，会自动处理依赖安装和构建
                    build.BuildB(buildType,buildshell)
                    env.JAR_FILE = sh(script: "find target -name '*.jar' -type f | head -1", returnStdout: true).trim()
                    // 生成带版本号的构建产物名称
                    env.ARTIFACT_NAME = "${projectName}-${BUILD_TIME}-${env.GIT_COMMIT}.tar.gz"
                    env.JAR_NAME = sh(script: "basename ${env.JAR_FILE}", returnStdout: true).trim()
                    // 保存部署信息
                    env.DEPLOY_INFO = """
                        版本: ${BUILD_TIME}-${env.GIT_COMMIT}
                        JAR包: ${env.JAR_NAME}
                    """
                    toemailF.Email(
                        currentBuild.currentResult,
                        "${Tenv}",
                        "${env.emailUser}",
                        "${JOB_NAME}",
                        "${branch}",
                        "${env.BUILD_USER}",
                        env.BUILD_TIME,
                        currentBuild.durationString ?: "N/A",
                        rollback,
                        "服务器: ${destIp}",
                        env.DEPLOY_INFO ?: "无部署信息",
                        "${srcURL}",
                        true
                    )
                }
            }
        }
        stage("打包并上传至minio"){
            when { expression { !rollback } }  // 非回滚时执行
            steps{
                script{
                    tools.PrintMsg("构建好的包上传至minio","image_tag")
                    sh """
                        tar -czf ${env.ARTIFACT_NAME} {env.JAR_FILE} launch.sh
                        mc cp ${env.ARTIFACT_NAME} myminio/${MINIO_BUCKET}/${projectName}/
                        mc cp ${env.JAR_FILE} myminio/${MINIO_BUCKET}/${JOB_NAME}/${env.JAR_NAME}
                    """
                    // 保存部署信息
                    env.DEPLOY_INFO = """
                        应用: ${projectName}
                        版本: ${BUILD_TIME}-${env.GIT_COMMIT}
                        JAR包: ${env.JAR_NAME}
                        包路径: ${MINIO_BUCKET}/${projectName}/${env.ARTIFACT_NAME}
                    """
                }
            }
        }
        stage("部署"){
            when { 
                allOf{
                    expression { !rollback } 
                    expression { isPublish }
                }
            }
            steps{
                script {
                    tools.PrintMsg("开始部署", "deploy")
                    currentStage = '部署'
                    withCredentials([
                        usernamePassword(
                            credentialsId: 'target-server-credential',
                            usernameVariable: 'SSH_USER',
                            passwordVariable: 'SSH_PASS'
                        ),
                        usernamePassword(
                            credentialsId: 'minio-credentials',
                            usernameVariable: 'MINIO_ACCESS_KEY',
                            passwordVariable: 'MINIO_SECRET_KEY'
                        )
                    ]) {
                        // 将destIp按逗号分割成数组
                        def servers = destIp.split(',')
                        servers.each { server ->
                            sh """
                                # 直接在SSH会话中生成签名和下载
                                sshpass -p \${SSH_PASS} ssh -o StrictHostKeyChecking=no \${SSH_USER}@${server} <<'EOS'
                                    cd ${destPath}
                                    rm -rf ${destPath}/*
                                    
                                    # 在远程服务器上重新生成签名
                                    DATE_VALUE_REMOTE=\$(date -R)
                                    SIGNATURE_REMOTE=\$(echo -en "GET\\n\\n\\n\${DATE_VALUE_REMOTE}\\n/${MINIO_BUCKET}/${JOB_NAME}/${env.ARTIFACT_NAME}" | 
                                        openssl sha1 -hmac "${MINIO_SECRET_KEY}" -binary | base64)
                                    
                                    curl -v -X GET -H "Date: \${DATE_VALUE_REMOTE}" \\
                                        -H "Authorization: AWS ${MINIO_ACCESS_KEY}:\${SIGNATURE_REMOTE}" \\
                                        -o ${env.ARTIFACT_NAME} \\
                                        "http://192.168.56.102:8021/${MINIO_BUCKET}/${JOB_NAME}/${env.ARTIFACT_NAME}"
                                    
                                    if [ -s ${env.ARTIFACT_NAME} ] && file ${env.ARTIFACT_NAME} | grep -q 'gzip compressed data'; then
                                        tar xzf ${env.ARTIFACT_NAME} -C ${destPath}/
                                        mv ${destPath}/dist/* ${destPath}
                                        rm -rf ${destPath}/dist ${destPath}/${env.ARTIFACT_NAME}
                                    else
                                        echo "下载的文件无效或不是gzip压缩包"
                                        exit 1
                                    fi
EOS
                            """
                        }
                    }
                }
            }
        }
        // 新增手动发布阶段
        stage("手动发布"){
            when { 
                allOf {
                    expression { !rollback }
                    expression { !isPublish }
                }
            }
            steps{
                script {
                    timeout(time: 1, unit: 'HOURS') {
                        def approval = input(
                            message: "确认要发布到${Tenv}环境吗？(等待时间: 1 小时)", 
                            ok: "确认发布"
                        )
                        
                        tools.PrintMsg("开始部署", "deploy")
                        currentStage = '手动发布'
                        withCredentials([
                            usernamePassword(
                                credentialsId: 'target-server-credential',
                                usernameVariable: 'SSH_USER',
                                passwordVariable: 'SSH_PASS'
                            ),
                            usernamePassword(
                                credentialsId: 'minio-credentials',
                                usernameVariable: 'MINIO_ACCESS_KEY',
                                passwordVariable: 'MINIO_SECRET_KEY'
                            )
                        ]) {
                            // 将destIp按逗号分割成数组
                            def servers = destIp.split(',')
                            servers.each { server ->
                                sh """
                                    # 直接在SSH会话中生成签名和下载
                                    sshpass -p \${SSH_PASS} ssh -o StrictHostKeyChecking=no \${SSH_USER}@${server} <<'EOS'
                                        cd ${destPath}
                                        rm -rf ${destPath}/*
                                        
                                        # 在远程服务器上重新生成签名
                                        DATE_VALUE_REMOTE=\$(date -R)
                                        SIGNATURE_REMOTE=\$(echo -en "GET\\n\\n\\n\${DATE_VALUE_REMOTE}\\n/${MINIO_BUCKET}/${JOB_NAME}/${env.ARTIFACT_NAME}" | 
                                            openssl sha1 -hmac "${MINIO_SECRET_KEY}" -binary | base64)
                                        
                                        curl -v -X GET -H "Date: \${DATE_VALUE_REMOTE}" \\
                                            -H "Authorization: AWS ${MINIO_ACCESS_KEY}:\${SIGNATURE_REMOTE}" \\
                                            -o ${env.ARTIFACT_NAME} \\
                                            "http://192.168.56.102:8021/${MINIO_BUCKET}/${JOB_NAME}/${env.ARTIFACT_NAME}"
                                        
                                        if [ -s ${env.ARTIFACT_NAME} ] && file ${env.ARTIFACT_NAME} | grep -q 'gzip compressed data'; then
                                            tar xzf ${env.ARTIFACT_NAME} -C ${destPath}/
                                            mv ${destPath}/dist/* ${destPath}
                                            rm -rf ${destPath}/dist ${destPath}/${env.ARTIFACT_NAME}
                                        else
                                            echo "下载的文件无效或不是gzip压缩包"
                                            exit 1
                                        fi
EOS
                                """
                            }
                        }
                    }  // 这里添加了timeout块的闭合括号
                }
            }
        }
        // 5. 回滚机制
        stage("回滚"){
            when { expression { rollback } }
            steps{
                script {
                    tools.PrintMsg("执行回滚", "rollback")
                    currentStage = '回滚'
                    // 获取可用版本列表
                    def versions = sh(script: "mc ls myminio/${MINIO_BUCKET}/${JOB_NAME}/ | awk '{print \$6}'", returnStdout: true).trim().split(',')
                    def selectedVersion = input(
                        message: '选择要回滚的版本', 
                        parameters: [
                            choice(name: 'selectedVersion', choices: versions.join(','), description: '可用的构建版本')
                        ]
                    )
                    // 设置回滚部署信息
                    env.DEPLOY_INFO = """
                        版本: ${selectedVersion}
                    """
                    
                    withCredentials([
                        usernamePassword(
                            credentialsId: 'target-server-credential',
                            usernameVariable: 'SSH_USER',
                            passwordVariable: 'SSH_PASS'
                        ),
                        usernamePassword(
                            credentialsId: 'minio-credentials',
                            usernameVariable: 'MINIO_ACCESS_KEY',
                            passwordVariable: 'MINIO_SECRET_KEY'
                        )
                    ]) {
                        // 将destIp按逗号分割成数组
                        def servers = destIp.split(',')
                        servers.each { server ->
                            sh """
                                sshpass -p \${SSH_PASS} ssh -o StrictHostKeyChecking=no \${SSH_USER}@${server} <<'EOS'
                                    cd ${destPath}
                                    rm -rf ${destPath}/*
                                    # 在远程服务器上生成签名
                                    DATE_VALUE_REMOTE=\$(date -R)
                                    SIGNATURE_REMOTE=\$(echo -en "GET\\n\\n\\n\${DATE_VALUE_REMOTE}\\n/${MINIO_BUCKET}/${JOB_NAME}/${selectedVersion}" | 
                                        openssl sha1 -hmac "${MINIO_SECRET_KEY}" -binary | base64)
                                    
                                    curl -v -X GET -H "Date: \${DATE_VALUE_REMOTE}" \\
                                        -H "Authorization: AWS ${MINIO_ACCESS_KEY}:\${SIGNATURE_REMOTE}" \\
                                        -o ${selectedVersion} \\
                                        "http://192.168.56.102:8021/${MINIO_BUCKET}/${JOB_NAME}/${selectedVersion}"
                                    
                                    if [ -s ${selectedVersion} ] && file ${selectedVersion} | grep -q 'gzip compressed data'; then
                                        tar xzf ${selectedVersion} -C ${destPath}/
                                        mv ${destPath}/dist/* ${destPath}/
                                        rm -rf ${destPath}/dist ${destPath}/${selectedVersion}
                                    else
                                        echo "下载的文件无效或不是gzip压缩包"
                                        exit 1
                                    fi
EOS
                            """
                        }
                    }
                }
            }
        }
    }
    post {
        always {
            script {
                TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"))
                env.BUILD_TIME = new Date().format("yyyyMMdd_HHmmss")
                def buildTime = env.BUILD_TIME ?: "N/A"
                def buildDuration = currentBuild.durationString ?: "N/A"
                if (currentStage in ['部署', '手动发布','回滚']){
                    def deployType = (currentStage == '手动发布') ? '手动发布' : '自动发布'
                    toemailF.Email(
                        currentBuild.currentResult,
                        "${Tenv}",
                        "${env.emailUser}",
                        "${JOB_NAME}",
                        "${branch}",
                        "${env.BUILD_USER}",
                        buildTime,
                        buildDuration,
                        rollback,
                        "服务器: ${destIp}",
                        env.DEPLOY_INFO ?: "无部署信息",
                        "${srcURL}"
                    )
                }
            }
        }
    }
}